from django.db.models import F
from math import radians, cos, sin, asin, sqrt
from .models_location import TechnicianLocation, ServiceArea, LocationHistory


def haversine_distance(lat1, lon1, lat2, lon2):
    """
    计算两个经纬度点之间的距离（单位：公里）
    """
    # 将十进制度数转化为弧度
    lat1, lon1, lat2, lon2 = map(radians, [float(lat1), float(lon1), float(lat2), float(lon2)])

    # haversine公式
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
    c = 2 * asin(sqrt(a))
    r = 6371  # 地球平均半径，单位为公里
    return c * r


class LocationService:
    """位置业务逻辑服务类"""

    @staticmethod
    def update_technician_location(technician, latitude, longitude, address=''):
        """更新技师位置"""
        # 更新或创建位置记录
        location, created = TechnicianLocation.objects.update_or_create(
            technician=technician,
            defaults={
                'latitude': latitude,
                'longitude': longitude,
                'address': address
            }
        )

        # 记录位置历史
        LocationHistory.objects.create(
            technician=technician,
            latitude=location.latitude,
            longitude=location.longitude,
            address=location.address
        )

        return location

    @staticmethod
    def get_technician_location(technician):
        """获取技师当前位置"""
        try:
            location = TechnicianLocation.objects.get(technician=technician)
            return location
        except TechnicianLocation.DoesNotExist:
            raise ValueError('未找到位置信息')

    @staticmethod
    def add_service_area(technician, data):
        """添加服务区域"""
        service_area = ServiceArea.objects.create(
            technician=technician,
            name=data['name'],
            latitude=data['latitude'],
            longitude=data['longitude'],
            radius=data['radius']
        )
        return service_area

    @staticmethod
    def get_service_areas(technician):
        """获取技师服务区域"""
        return ServiceArea.objects.filter(technician=technician)

    @staticmethod
    def delete_service_area(technician, area_id):
        """删除服务区域"""
        try:
            service_area = ServiceArea.objects.get(id=area_id, technician=technician)
            service_area.delete()
            return True
        except ServiceArea.DoesNotExist:
            raise ValueError('服务区域不存在')

    @staticmethod
    def get_nearby_technicians(latitude, longitude, max_distance=10, page=1, page_size=10):
        """获取附近技师"""
        # 获取所有技师位置
        technician_locations = TechnicianLocation.objects.select_related('technician').filter(
            technician__is_verified=True
        )

        # 计算距离并筛选
        nearby_technicians = []
        for location in technician_locations:
            distance = haversine_distance(
                latitude, longitude,
                float(location.latitude), float(location.longitude)
            )

            if distance <= max_distance:
                # 获取技师的服务类型信息
                service_types = list(location.technician.service_types.values_list('name', flat=True)) if hasattr(location.technician, 'service_types') else []

                nearby_technicians.append({
                    'technician': {
                        'id': location.technician.id,
                        'name': location.technician.real_name,
                        'avatar': location.technician.avatar.url if location.technician.avatar else None,
                        'rating': location.technician.rating,
                        'order_count': getattr(location.technician, 'order_count', 0),
                        'service_types': service_types
                    },
                    'latitude': float(location.latitude),
                    'longitude': float(location.longitude),
                    'distance': round(distance, 2),
                    'last_updated': location.updated_at.strftime('%Y-%m-%d %H:%M:%S')
                })

        # 按距离排序
        nearby_technicians.sort(key=lambda x: x['distance'])

        # 分页处理
        start_index = (page - 1) * page_size
        end_index = start_index + page_size
        paginated_technicians = nearby_technicians[start_index:end_index]

        # 返回结果
        response_data = {
            'results': paginated_technicians,
            'count': len(nearby_technicians),
            'page': page,
            'page_size': page_size,
            'has_next': end_index < len(nearby_technicians)
        }

        return response_data

    @staticmethod
    def get_location_history(technician):
        """获取位置历史记录"""
        # 获取最近30条记录
        history = LocationHistory.objects.filter(technician=technician)[:30]
        return history
